﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using XemlUtilities.ISA.Ontology;
using XemlUtilities.ISA.Protocol;
using XemlUtilities.DataSet;

namespace XemlUtilities.ISA
{
    class Investigation
    {
        public static MemoryStream GetStream(XemlDataSet xds, Guid xemlId, string connectionString)
        {
            MemoryStream res = new MemoryStream();
            StreamWriter txtWriter = new StreamWriter(res);

            // some ontology references are only created in this file, so init them here
            OntologyBase OBIOntology = OntologyBase.GetOrCreateOntology("OBI");

            Term OBIMetaboliteProfiling = OntologyBase.GetOrCreateTermName("OBI", "metabolite profiling");
            OBIMetaboliteProfiling.AccessionNr = "366";
            Term OBIMassSpec = OntologyBase.GetOrCreateTermName("OBI", "mass spectrometry");
            OBIMassSpec.AccessionNr = "OBI_0000470";

            Term OBIInterventionDesign = OntologyBase.GetOrCreateTermName("OBI", "intervention design");
            OBIInterventionDesign.AccessionNr = "OBI_0000115";

            Term OBIStimilusStress = OntologyBase.GetOrCreateTermName("OBI", "stimulus or stress design");
            OBIStimilusStress.AccessionNr = "OBI_0001396";

            txtWriter.WriteLine("ONTOLOGY SOURCE REFERENCE");
            //txtWriter.WriteLine(string.Join(IsaExporter.multipleFieldDelimiter, new[] {"Term Source Name"}.Concat(IsaExporter.Encapsulate(IsaExporter.fieldEncapsulater, new[] {"OBI", "NCBITaxon", "XEO", "PO_Structure", "EO", "XEO_Positioning", "Chemical Methods Ontology" }))));
            //txtWriter.WriteLine(string.Join(IsaExporter.multipleFieldDelimiter, new[] {"Term Source File"}.Concat(IsaExporter.Encapsulate(IsaExporter.fieldEncapsulater, new[] {string.Empty, "http://bioportal.bioontology.org/ontologies/38802", "http://bioportal.bioontology.org/ontologies/3176", "http://www.plantontology.org/", "http://bioportal.bioontology.org/ontologies/45260", string.Empty, "http://www.rsc.org/ontologies/CMO/"}))));
            //txtWriter.WriteLine(string.Join(IsaExporter.multipleFieldDelimiter, new[] {"Term Source Version"}.Concat(IsaExporter.Encapsulate(IsaExporter.fieldEncapsulater, new[] {string.Empty, "38802", "today", "today", "today", "today", ""}))));
            //txtWriter.WriteLine(string.Join(IsaExporter.multipleFieldDelimiter, new[] {"Term Source Description"}.Concat(IsaExporter.Encapsulate(IsaExporter.fieldEncapsulater, new[] {"Ontology for Biomedical Investigations", "NCBI organismal classification", "XEML Environmental Ontology", "Plant Ontology (Structure)", "Plant Environmental Ontology", "XEML Plant Positioning Ontology", "Chemical Methods Ontology"}))));

            txtWriter.WriteLine(string.Join(IsaExporter.multipleFieldDelimiter, new[] { "Term Source Name" }.Concat(IsaExporter.Encapsulate(IsaExporter.fieldEncapsulater, OntologyBase.GetOntologies().Select(x => x.Acronym).ToArray()))));
            txtWriter.WriteLine(string.Join(IsaExporter.multipleFieldDelimiter, new[] { "Term Source File" }.Concat(IsaExporter.Encapsulate(IsaExporter.fieldEncapsulater, OntologyBase.GetOntologies().Select(x => x.OntologyURL).ToArray()))));
            txtWriter.WriteLine(string.Join(IsaExporter.multipleFieldDelimiter, new[] { "Term Source Version" }.Concat(IsaExporter.Encapsulate(IsaExporter.fieldEncapsulater, OntologyBase.GetOntologies().Select(x => x.Version).ToArray()))));
            txtWriter.WriteLine(string.Join(IsaExporter.multipleFieldDelimiter, new[] { "Term Source Description" }.Concat(IsaExporter.Encapsulate(IsaExporter.fieldEncapsulater, OntologyBase.GetOntologies().Select(x => x.Name).ToArray()))));

            txtWriter.WriteLine("INVESTIGATION");
            txtWriter.WriteLine("Investigation Identifier\t{0}", QuotedEmptyString());
            txtWriter.WriteLine("Investigation Title\t{0}", QuotedEmptyString());
            txtWriter.WriteLine("Investigation Description\t{0}", QuotedEmptyString());
            txtWriter.WriteLine("Investigation Submission Date\t{0}", QuotedEmptyString());
            txtWriter.WriteLine("Investigation Public Release Date\t{0}", QuotedEmptyString());

            txtWriter.WriteLine("INVESTIGATION PUBLICATIONS");
            txtWriter.WriteLine("Investigation PubMed ID\t{0}", QuotedEmptyString());
            txtWriter.WriteLine("Investigation Publication DOI\t{0}", QuotedEmptyString());
            txtWriter.WriteLine("Investigation Publication Author List\t{0}", QuotedEmptyString());
            txtWriter.WriteLine("Investigation Publication Title\t{0}", QuotedEmptyString());
            txtWriter.WriteLine("Investigation Publication Status\t{0}", QuotedEmptyString());
            txtWriter.WriteLine("Investigation Publication Status Term Accession Number\t{0}", QuotedEmptyString());
            txtWriter.WriteLine("Investigation Publication Status Term Source REF\t{0}", QuotedEmptyString());

            txtWriter.WriteLine("INVESTIGATION CONTACTS");
            txtWriter.WriteLine("Investigation Person Last Name\t{0}", QuotedEmptyString());
            txtWriter.WriteLine("Investigation Person First Name\t{0}", QuotedEmptyString());
            txtWriter.WriteLine("Investigation Person Mid Initials\t{0}", QuotedEmptyString());
            txtWriter.WriteLine("Investigation Person Email\t{0}", QuotedEmptyString());
            txtWriter.WriteLine("Investigation Person Phone\t{0}", QuotedEmptyString());
            txtWriter.WriteLine("Investigation Person Fax\t{0}", QuotedEmptyString());
            txtWriter.WriteLine("Investigation Person Address\t{0}", QuotedEmptyString());
            txtWriter.WriteLine("Investigation Person Affiliation\t{0}", QuotedEmptyString());
            txtWriter.WriteLine("Investigation Person Roles\t{0}", QuotedEmptyString());
            txtWriter.WriteLine("Investigation Person Roles Term Accession Number\t{0}", QuotedEmptyString());
            txtWriter.WriteLine("Investigation Person Roles Term Source REF\t{0}", QuotedEmptyString());

            txtWriter.WriteLine("STUDY");
            txtWriter.WriteLine("Study Identifier\t{0}", IsaExporter.Encapsulate(xds.Document.Single().XemlId.ToString()));
            txtWriter.WriteLine("Study Title\t{0}", IsaExporter.Encapsulate(xds.Document.Single().Name));
            txtWriter.WriteLine("Study Description\t{0}", IsaExporter.Encapsulate(xds.Document.Single().IsDescriptionNull() ? string.Empty : xds.Document.Single().Description.Replace(Environment.NewLine, " ")));
            txtWriter.WriteLine("Study Submission Date\t{0}", IsaExporter.Encapsulate(xds.Document.Single().StartDate.ToString("yyyy-MM-dd", System.Globalization.CultureInfo.InvariantCulture)));
            txtWriter.WriteLine("Study Public Release Date\t{0}", IsaExporter.Encapsulate(DateTime.Now.ToString("yyyy-MM-dd", System.Globalization.CultureInfo.InvariantCulture)));
            txtWriter.WriteLine("Study File Name\t{0}", IsaExporter.Encapsulate(Study.GetFileName(xds)));

            txtWriter.WriteLine("STUDY DESIGN DESCRIPTORS");
            txtWriter.WriteLine(String.Concat("Study Design Type\t", String.Join(IsaExporter.multipleFieldDelimiter, IsaExporter.Encapsulate(new[] { OBIInterventionDesign.Name, OBIStimilusStress.Name }))));
            txtWriter.WriteLine(String.Concat("Study Design Type Term Accession Number\t", String.Join(IsaExporter.multipleFieldDelimiter, IsaExporter.Encapsulate(new[] { OBIInterventionDesign.URI, OBIStimilusStress.URI }))));
            txtWriter.WriteLine(String.Concat("Study Design Type Term Source REF\t", String.Join(IsaExporter.multipleFieldDelimiter, IsaExporter.Encapsulate(new[] { OBIInterventionDesign.Ontology.Acronym, OBIStimilusStress.Ontology.Acronym }))));

            txtWriter.WriteLine("STUDY PUBLICATIONS");
            txtWriter.WriteLine("Study PubMed ID\t{0}", QuotedEmptyString());
            string[] dois = IsaExporter.Encapsulate(xds.ExperimentKeywords.Where(x => x.Keyword.StartsWith("doi:")).Select(x => x.Keyword).ToArray());
            txtWriter.WriteLine("Study Publication DOI\t{0}", dois.Count() == 0 ? IsaExporter.Encapsulate(string.Empty) : string.Join(IsaExporter.multipleFieldDelimiter, dois));
            txtWriter.WriteLine("Study Publication Author List\t{0}", QuotedEmptyString());
            txtWriter.WriteLine("Study Publication Title\t{0}", QuotedEmptyString());
            txtWriter.WriteLine("Study Publication Status\t{0}", dois.Count() == 0 ? IsaExporter.Encapsulate("unpublished") : IsaExporter.Encapsulate("published"));
            txtWriter.WriteLine("Study Publication Status Term Accession Number\t{0}", QuotedEmptyString());
            txtWriter.WriteLine("Study Publication Status Term Source REF\t{0}", QuotedEmptyString());

            List<Protocol.ProtocolBase> protocols = Protocol.ProtocolBase.GetProtocols().ToList();
            List<Protocol.Growth.GrowthStep> growthSteps = (protocols.Single(x => x is Protocol.Growth) as Protocol.Growth).GetGrowthSteps().Distinct().ToList();

            txtWriter.WriteLine("STUDY FACTORS");
            txtWriter.WriteLine("Study Factor Name\t{0}", string.Join(IsaExporter.multipleFieldDelimiter, growthSteps.Select(x => IsaExporter.Encapsulate(x.ToString())).ToList()));
            txtWriter.WriteLine("Study Factor Type\t{0}", string.Join(IsaExporter.multipleFieldDelimiter, growthSteps.Select(x => IsaExporter.Encapsulate(x.Context)).ToList()));
            txtWriter.WriteLine("Study Factor Type Term Accession Number\t{0}", string.Join(IsaExporter.multipleFieldDelimiter, growthSteps.Select(x => IsaExporter.Encapsulate(x.term.URI)).ToList()));
            txtWriter.WriteLine("Study Factor Type Term Source REF\t{0}", string.Join(IsaExporter.multipleFieldDelimiter, IsaExporter.Encapsulate(growthSteps.Select(x => x.term.Ontology.Acronym).ToList())));

            txtWriter.WriteLine("STUDY ASSAYS");
            txtWriter.WriteLine("Study Assay File Name\t{0}", IsaExporter.Encapsulate(Assay.GetFileName(xds)));
            txtWriter.WriteLine("Study Assay Measurement Type\t{0}", IsaExporter.Encapsulate(OBIMetaboliteProfiling.Name));  //ok by Philippe
            txtWriter.WriteLine("Study Assay Measurement Type Term Accession Number\t{0}", IsaExporter.Encapsulate(OBIMetaboliteProfiling.URI)); //http://purl.obolibrary.org/obo/OBI_0000366
            txtWriter.WriteLine("Study Assay Measurement Type Term Source REF\t{0}", IsaExporter.Encapsulate(OBIOntology.Acronym));
            txtWriter.WriteLine("Study Assay Technology Type\t{0}", IsaExporter.Encapsulate(OBIMassSpec.Name));
            txtWriter.WriteLine("Study Assay Technology Type Term Accession Number\t{0}", IsaExporter.Encapsulate(OBIMassSpec.URI));  //http://purl.obolibrary.org/obo/OBI_0000470
            txtWriter.WriteLine("Study Assay Technology Type Term Source REF\t{0}", IsaExporter.Encapsulate(OBIOntology.Acronym));
            txtWriter.WriteLine("Study Assay Technology Platform\t{0}", IsaExporter.Encapsulate("GC-MS"));

            List<Term> protocolAccNrs = protocols.Select(x => x.AccessionNr).ToList();

            txtWriter.WriteLine("STUDY PROTOCOLS");
            txtWriter.WriteLine("Study Protocol Name\t{0}", string.Join(IsaExporter.multipleFieldDelimiter, IsaExporter.Encapsulate(protocols.Select(x => x.Name).ToList())));
            txtWriter.WriteLine("Study Protocol Type\t{0}", string.Join(IsaExporter.multipleFieldDelimiter, IsaExporter.Encapsulate(protocols.Select(x => x.Type).ToList())));
            txtWriter.WriteLine("Study Protocol Type Term Accession Number\t{0}", string.Join(IsaExporter.multipleFieldDelimiter, IsaExporter.Encapsulate(protocolAccNrs.Select(x => x != null ? x.URI : String.Empty).ToList())));
            txtWriter.WriteLine("Study Protocol Type Term Source REF\t{0}", string.Join(IsaExporter.multipleFieldDelimiter, IsaExporter.Encapsulate(protocolAccNrs.Select(x => x != null ? x.Ontology.Acronym : String.Empty).ToList())));
            txtWriter.WriteLine("Study Protocol Description\t{0}", string.Join(IsaExporter.multipleFieldDelimiter, IsaExporter.Encapsulate(protocols.Select(x => x.Description).ToList())));
            txtWriter.WriteLine("Study Protocol URI\t{0}", string.Join(IsaExporter.multipleFieldDelimiter, IsaExporter.Encapsulate(protocols.Select(x => string.Format(XemlDataSet.DocumentDataTable.UriTemplate, xemlId)).ToList())));
            txtWriter.WriteLine("Study Protocol Version\t{0}", EmptyProtocolPlaceholder(protocols));

            txtWriter.WriteLine("Study Protocol Parameters Name\t{0}", string.Join(IsaExporter.multipleFieldDelimiter, IsaExporter.Encapsulate(protocols.Select(x => string.Join(IsaExporter.multipleValueDelimiter, x.GetParameters().Select(y => y.Name))).ToList())));

            //jahu: to test validation I just implement empty placeholders for the prtocol part, see next 2 lines of source code
            //txtWriter.WriteLine("Study Protocol Parameters Name Term Accession Number\t{0}", string.Join(IsaExporter.multipleFieldDelimiter, IsaExporter.Encapsulate(protocols.Select(x => string.Join(IsaExporter.multipleValueDelimiter, x.GetParameters().Select(y => y.AccessionNr != null ? y.AccessionNr.AccessionNr : ""))).ToList())));
            //txtWriter.WriteLine("Study Protocol Parameters Name Term Source REF\t{0}", string.Join(IsaExporter.multipleFieldDelimiter, IsaExporter.Encapsulate(protocols.Select(x => string.Join(IsaExporter.multipleValueDelimiter, x.GetParameters().Select(y => y.AccessionNr != null ? y.AccessionNr.Ontology.Acronym : ""))).ToList())));

            //next 2 lines to be removed ones the validation imporves
            txtWriter.WriteLine("Study Protocol Parameters Name Term Accession Number\t{0}", string.Join(IsaExporter.multipleFieldDelimiter, IsaExporter.Encapsulate(protocols.Select(x => string.Join(IsaExporter.multipleValueDelimiter, x.GetParameters().Select(y => y.AccessionNr != null ? string.Empty : string.Empty))).ToList())));
            txtWriter.WriteLine("Study Protocol Parameters Name Term Source REF\t{0}", string.Join(IsaExporter.multipleFieldDelimiter, IsaExporter.Encapsulate(protocols.Select(x => string.Join(IsaExporter.multipleValueDelimiter, x.GetParameters().Select(y => y.AccessionNr != null ? string.Empty : string.Empty))).ToList())));


            txtWriter.WriteLine("Study Protocol Components Name\t{0}", EmptyProtocolPlaceholder(protocols));
            txtWriter.WriteLine("Study Protocol Components Type\t{0}", EmptyProtocolPlaceholder(protocols));
            txtWriter.WriteLine("Study Protocol Components Type Term Accession Number\t{0}", EmptyProtocolPlaceholder(protocols));
            txtWriter.WriteLine("Study Protocol Components Type Term Source REF\t{0}", EmptyProtocolPlaceholder(protocols));

            txtWriter.WriteLine("STUDY CONTACTS");
            txtWriter.WriteLine("Study Person Last Name\t{0}", IsaExporter.Encapsulate(xds.Document.Single().IsExperimenterLastNameNull() ? string.Empty : xds.Document.Single().ExperimenterLastName));
            txtWriter.WriteLine("Study Person First Name\t{0}", IsaExporter.Encapsulate(xds.Document.Single().IsExperimenterFirstNameNull() ? string.Empty : xds.Document.Single().ExperimenterFirstName));
            txtWriter.WriteLine("Study Person Mid Initials\t{0}", QuotedEmptyString());
            txtWriter.WriteLine("Study Person Email\t{0}", IsaExporter.Encapsulate(xds.Document.Single().IsExperimenterEmailNull() ? string.Empty : xds.Document.Single().ExperimenterEmail));
            txtWriter.WriteLine("Study Person Phone\t{0}", QuotedEmptyString());
            txtWriter.WriteLine("Study Person Fax\t{0}", QuotedEmptyString());
            txtWriter.WriteLine("Study Person Address\t{0}", QuotedEmptyString());
            txtWriter.WriteLine("Study Person Affiliation\t{0}", IsaExporter.Encapsulate(xds.Document.Single().IsOrganisationNull() ? string.Empty : xds.Document.Single().Organisation));
            txtWriter.WriteLine("Study Person Roles\t{0}", IsaExporter.Encapsulate("Experimenter"));
            txtWriter.WriteLine("Study Person Roles Term Accession Number\t{0}", QuotedEmptyString());
            txtWriter.WriteLine("Study Person Roles Term Source REF\t{0}", QuotedEmptyString());

            txtWriter.WriteLine("Comment[ISA generated by]\tGolm Metabolome Database via XEML");
            txtWriter.Flush();
            res.Seek(0, SeekOrigin.Begin);
            return res;
        }

        private static string EmptyProtocolPlaceholder(List<Protocol.ProtocolBase> protocols)
        {
            return string.Join(IsaExporter.multipleFieldDelimiter, Enumerable.Repeat("\"\"", protocols.Count));
        }

        private static String QuotedEmptyString()
        {
            return String.Concat(IsaExporter.fieldEncapsulater, IsaExporter.fieldEncapsulater);
        }

        public static string GetFileName(XemlDataSet xds)
        {
            return string.Format("i_{0}.txt", xds.Document.Single().PutativeFileName);
        }
    }
}
